perm filename MEMTST.PAL[11,HE] blob
sn#604747 filedate 1981-08-12 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00008 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 .TITLE Memory Diagnostic
C00008 00003 First initialize the mapper
C00013 00004 Control loop for tests
C00016 00005 Now lets do some tests!
C00022 00006 Error trap handlers: NXM, MPRTRP, PARERR
C00025 00007 ERROR, SETMAP & I/O Routines
C00030 00008 Constants & Data
C00033 ENDMK
C⊗;
.TITLE Memory Diagnostic
;written by ARG 7/77 - modified for regular memory 7/79
COMMENT ⊗ This is a program to test out the memory on the PDP 11/45.
There are 6 tests. Four write a given pattern into memory and then read it back.
The patterns are all zeros, all ones, and two checkerboard patterns. The next two
tests check out the addressing by writing the address of each location, or the
complement of the address, in that location. The regular addresses are written
in ascending order, while the complements are written in descending order.
Each test can be explicitly specified or the first 6 can be cycled through
automatically. Which 8K chunk of the 64K memory is to be used can also
be explicitly chosen or all 8 chunks can be cycled through.
When an error is encountered the program types out the memory's address, the
value that was expected, and the value read. R5 contains the virtual address of
the bad location. The program can be told to break to DDT when an error occurs.
A count of the errors encountered is kept and it may be displayed. It is also
possible to suppress error print out.
At the conclusion of each test or test cycle a counter is incremented and displayed
showing the number of tests performed. It is possible to break to DDT upon
completion of the test in progress.
Control of the program is accomplished by use of the front panel switches as
shown below:
_________________________________________________________________________
| | | | | | | | | | | |
| | | | | |loop break select |
| |run|display | test # |on type| to| | or| which 8K |
| | or| | | | |out|DDT| cycle |
| |DDT| | | (0-6) error | on| |mem| (0-7) |
| | | | | | | error | | |
| X X | | | X X | | | | | X X | | |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|
17 16 15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 0
Explanation of switch settings:
Run/DDT - if up break to DDT at completion of current test
display - if up display # of errors in lights, else display the number
of tests performed (iteration count)
test # - number from 0 to 6 to select test:
0 cycle through tests 1-6
1 write all zeros
2 write all ones
3 write checkerboard 0101...
4 write checkerboard 1010...
5 addresses (ascending)
6 complement of addresses (descending)
loop on error - if switch 8 is up, loop on error for tests 1 - 4.
typeout - if switches 6 & 7 are both down then no typeout is printed
if either is up then error messages are typed
break to DDT on errors - if up does just that
select/cycle - if up selects 8K chunk specified by last three switches
if down cycles through all eight chunks
Typing any character while errors are being typed out will cause the 11 to go
into a hold on output until another character is typed.
⊗
;First initialize the mapper
.INSRT STUFF.PAL[11,ARG]
.INSRT MAPPER.PAL[AL,HE]
LOW= 100000 ;Memory gets mapped from 100 000 to 137 777
HI = 140000
.=4
NXM
340
.=114 ;PARITY ERROR TRAP
PARERR
340
.=250
MPRTRP
340
.=1000
START: RESET
MOV #START,SP ;Set up the stack
MOV #BEGMES,R1 ;Tell world who we are
JSR PC,OUTSTR
MOV #CRLF,R1
JSR PC,OUTSTR
; Set up the four page tables
; Virtual address Physical address
; 0 - 77777 Core 0 - 7777
; 100000 - 137777 Memory to test 100000 - 137777
; 140000 - 157777 unused
; 160000 - 177777 I/O 760000 - 777777
PINIT: MOV #KISDR0,R1 ;Set up Kernel's Page Descriptor Registers
MOV #20,R0 ;do both I & D spaces - 8 registers each
1$: MOV #MAPRW+MAPPLF,(R1)+ ;Read/Write - full size {4K = 200 blocks}
SOB R0,1$
MOV #PGTBL0,R1 ;Map 0, transparent
MOV #KISAR0,R2
MOV #KDSAR0,R3
MOV #10,R0 ;Set up Kernel I & D space mappings
2$: MOV (R1),(R2)+
MOV (R1)+,(R3)+
SOB R0,2$
MOV #7,MAPSR3 ;Enable I & D spaces
MOV #MAPENB,MAPSR0 ;Turn the map on
;Control loop for tests
MOV #5,TEST ;Initialize some values
MOV #7,CHUNK
CLR ERRNUM ;Zero error count
CLR PARNUM ;Zero parity error count
CLR ITER ;Zero count of # times through
TLOOP: BIT #10,@VSW ;Select one 8K chunk or cycle through?
BEQ 1$
MOV @VSW,CHUNK ;Get selected 8K chunk
BIC #177770,CHUNK
BR 4$
1$: BIT #7000,@VSW ;Are we cycling through tests too?
BEQ 3$
2$: INC CHUNK ; No - test next chunk
BIC #10,CHUNK
BR 4$
3$: CMP #5,TEST ; Yes - only move to next 8K chunk if #test = 5
BLE 2$
4$: JSR PC,SETMAP ;Select the proper 8K chunk
MOV @VSW,R0 ;See what test we're to do
ASH #-11,R0 ;Move test # to low 3 bits - shift right 9
BIC #177770,R0
BNE 6$ ;Skip ahead & jump to selected test, unless cycling
MOV TEST,R0 ;Get # of last test done
INC R0 ;Do next one
CMP #6,R0
BGT 5$
CLR R0 ;Only cycle through first 6 tests
5$: INC R0
6$: DEC R0 ;Correct for table
MOV R0,TEST ;Remember it
ROL R0 ;Offset in words
JSR PC,@TESTS(R0) ;Go do test
MOV @VSW,R0 ;Get test #
ASH #-11,R0
INC R0
BIC #177770,R0
BEQ 8$ ;Update ITER count if test # = 7
BIT #7000,@VSW ;See if it's time to update ITER count
BNE 7$ ;Cycling through tests?
CMP #5,TEST ; If so don't update ITER unless #test = 5
BGT 9$
7$: BIT #10,@VSW ;Cycling through memory
BNE 8$ ;If not go increment ITER
CMP #7,CHUNK ; else only if CHUNK = 7
BNE 9$
8$: INC ITER
9$: MOV ITER,R0
BIT #40000,@VSW ;Who to display?
BEQ 10$ ; Display # times through
MOV ERRNUM,R0 ; Display # errors
10$: MOV R0,%SWR
BIT #100000,@VSW ;Keep running
BEQ 11$
BPT ; Or break to DDT
11$: JMP TLOOP ;Repeat it all again
;Now lets do some tests!
TEST1: CLR R4 ;Write and read all zeros
JMP PATTST
TEST2: MOV #177777,R4 ;Write and read all ones
JMP PATTST
TEST3: MOV #052525,R4 ;The two checkerboard patterns: 0101010101010101
JMP PATTST
TEST4: MOV #125252,R4 ; & 1010101010101010 (these test noise immunity)
JMP PATTST
PATTST: MOV #LOW,R5 ;Auxiliary routine for tests 1-4
CLR WRTRD ;Indicate we're writing
P1: MOV R4,(R5)+ ;Write pattern
CMP R5,#HI ;See if done
BLO P1 ;No - keep looping
MOV #LOW,R5
INC WRTRD ;Indicate we're reading
mov #2,r2 ;TED
P2: MOV (R5),R3 ;Read pattern
CMP R4,R3 ; & check it
BEQ 3$ ;If ok skip ahead
JSR PC,ERROR ; else call the error routine
BPT ; & break to DDT
mov #2,r2 ;TED
bit #400,@VSW ;TED - loop on error?
beq 2$ ;TED
clr r2 ;TED - set loop flag
2$: bit #100000,@VSW ;TED - get out?
bne 4$
3$: add r2,r5 ;TED - are we looping on error?
CMP R5,#HI ;See if done with this 8K
BLO P2 ;No - keep looping
4$: RTS PC
PATERR: ADD #2,R5 ;Keep going with next word
CMP R5,#HI
BLO 1$ ; & then resume testing
RTS PC ; but don't go too far - return if done
1$: TST WRTRD ;Where were we when the parity error zapped us?
BNE P2 ;Reading
BR P1 ;Still writing
;This test writes the address of each location in that location.
;First we write all the addresses and then we read them.
;This and the next test confirm that each address accesses a unique location
TEST5: MOV #LOW,R5
CLR WRTRD ;Indicate we're writing
T51: MOV R5,(R5)+ ;Write the location's address (ascending)
CMP R5,#HI ;See if done
BLO T51 ;No - keep looping
MOV #LOW,R5
INC WRTRD ;Indicate we're reading
T52: MOV (R5),R3 ;Read value
CMP R5,R3 ;Check that location has correct value
BEQ 3$
MOV R5,R4 ;So error routine knows what value was expected
JSR PC,ERROR ;Call error routine
BPT ; & break to DDT
3$: ADD #2,R5 ;Next address to check
CMP R5,#HI ;See if done
BLO T52 ;No - keep looping
RTS PC
T5ERR: ADD #2,R5 ;Keep going continuing with next word
CMP R5,#HI
BLO 1$ ; but don't go too far
RTS PC ; return if done
1$: TST WRTRD ;Where were we when the parity error zapped us?
BNE T52 ;Reading
BR T51 ;Still writing
;As above but write the complement of each address and work from the high
;to the low addresses
TEST6: MOV #HI-2,R5
CLR WRTRD ;Indicate we're writing
T61: MOV R5,R4 ;Write the complement of the location's address
COM R4
MOV R4,(R5)
SUB #2,R5 ;Point to next word (descending)
CMP R5,#LOW ;See if done
BHIS T61 ;No - keep looping
MOV #HI-2,R5
INC WRTRD ;Indicate we're reading
T62: MOV R5,R4 ;Get complement of address in R4
COM R4
MOV (R5),R3 ;Read value
CMP R4,R3 ;Check that location has correct value
BEQ 3$
JSR PC,ERROR ;Call error routine
BPT ; & break to DDT
3$: SUB #2,R5 ;Next address to check
CMP R5,#LOW ;See if done
BHIS T62 ;No - keep looping
RTS PC
T6ERR: SUB #2,R5 ;Keep going continuing with next word
CMP R5,#LOW
BHIS 1$ ; but don't go too far
RTS PC ; return if done
1$: TST WRTRD ;Where were we when the parity error zapped us?
BNE T62 ;Reading
BR T61 ;Still writing
;Error trap handlers: NXM, MPRTRP, PARERR
NXM: MOV #NXMMES,R1 ;Print nxm error message
BR TRP
MPRTRP: MOV #MAPMES,R1 ;Print map trap error message
TRP: JSR PC,OUTSTR
MOV CHUNK,R0 ;Get high 3 bits of memory address
BIC #177770,R0
MOV R5,R1 ;Get low 14 bits
SUB #LOW,R1 ;Get rid of offset
ASH #2,R1 ;Shift low 14 bits over 2 to the left
ASHC #-1,R0 ;Shift all 17 bits over 1 to the right
; ADD #'0,R0 ;Print the high 2 bits - 0-64K offset
ADD #'1,R0 ;Print the high 2 bits - actual unibus address
JSR PC,OUTCHR
JSR PC,OUTNM1 ;& then print the low 15 bits
MOV #CRLF,R1
JSR PC,OUTSTR ;Skip a line
TRPRET: RTI ;*** for NXM debugging ***
MOV 16,PS ;Now make it look like the bad instruction
JMP @14 ; did a BPT to DDT
PARERR: INC PARNUM ;Update # of parity errors encountered
MOV #ERR1P,R1 ;Print "parity error"
JSR PC,OUTSTR
JSR PC,ERROR ;Call error routine to print info (?)
SEC ;no-op - break to DDT if desired later
PARRET: MOV #1,PARCSR ;Re-enable parity trapping
MOV #CRLF,R1 ;Parity trap return code
JSR PC,OUTSTR
ADD #4,SP ;Clean up stack (error routines can still use PC)
BIT #200,%TKS ;SOMEBODY TYPED SOMETHING?
BEQ 6$
JSR PC,HOLD
TST %TKB ;CLEAR READY FLAG
5$: BIT #200,%TKS ;SOMEBODY TYPED SOMETHING?
BEQ 5$
JSR PC,UNHOLD
TST %TKB ;CLEAR READY FLAG
6$: BIT #100,@VSW ;Break to DDT on errors?
BEQ 7$
BPT ;Yes - go to DDT
7$: MOV TEST,R0 ;Get # of current test
ROL R0
JMP @TSTERR(R0) ;Go to the appropriate error entry for this test
;ERROR, SETMAP & I/O Routines
ERROR: INC ERRNUM ;Update error count
BIT #300,@VSW ;See if typeout or break to DDT on errors set
BEQ 1$
MOV #ERR1,R1 ;Print "Error at address:"
JSR PC,OUTSTR
MOV CHUNK,R0 ;Get high 3 bits of memory address
BIC #177770,R0
MOV R5,R1 ;Get low 14 bits
SUB #LOW,R1 ;Get rid of offset
ASH #2,R1 ;Shift low 14 bits over 2 to the left
ASHC #-1,R0 ;Shift all 17 bits over 1 to the right
; ADD #'0,R0 ;Print the high 2 bits - 0-64K offset
ADD #'1,R0 ;Print the high 2 bits - actual unibus address
JSR PC,OUTCHR
JSR PC,OUTNM1 ;& then print the low 15 bits
MOV #ERR2,R1 ;Print "Value should be:"
JSR PC,OUTSTR
MOV R4,R1 ;Print the expected value
JSR PC,OUTNUM
MOV #ERR3,R1 ;Print "But was:"
JSR PC,OUTSTR
MOV R3,R1 ;Print the real value
JSR PC,OUTNUM
mov #err5,r1 ;print "test#"
jsr pc,outstr
mov test,r0 ;print test#
add #61,r0
jsr pc,outchr
MOV #CRLF,R1 ;Skip a line
JSR PC,OUTSTR
BIT #200,%TKS ;SOMEBODY TYPED SOMETHING?
BEQ 1$
JSR PC,HOLD
TST %TKB ;CLEAR READY FLAG
4$: BIT #200,%TKS ;SOMEBODY TYPED SOMETHING?
BEQ 4$
JSR PC,UNHOLD
TST %TKB ;CLEAR READY FLAG
1$: BIT #100,@VSW ;Break to DDT on errors?
BNE 2$
ADD #2,(SP) ;If not skip over the BPT following the JSR to ERROR
2$: BIT #40000,@VSW ;Should we display the new error count
BEQ 3$
MOV ERRNUM,%SWR ;Display error count in lights
3$: RTS PC
HLDMS: .BYTE 16
.BYTE 40
.REPT 4
.BYTE 200 ;FILLER FOR 2400 BAUD
.ENDR
.BYTE 40
.ASCII /****HOLDING****/
.BYTE 36
.BYTE 16
.BYTE 63
.REPT 4
.BYTE 200 ;FILLER FOR 2400 BAUD
.ENDR
.BYTE 40
.BYTE 0
.EVEN
UHLDMS: .BYTE 16
.BYTE 40
.REPT 4
.BYTE 200 ;FILLER FOR 2400 BAUD
.ENDR
.BYTE 40
.BYTE 36
.BYTE 16
.BYTE 63
.REPT 4
.BYTE 200 ;FILLER FOR 2400 BAUD
.ENDR
.BYTE 40
.BYTE 0
.EVEN
SETMAP: MOV CHUNK,R1 ;Get which 8K to map to
MUL #400,R1 ;Compute physical address of chunk
ADD #1000,R1 ; adding in an offset of 100000
MOV R1,KDSAR0+10 ;V.Loc 100000 to 117777 goes to P.Loc of chunk
ADD #200,R1
MOV R1,KDSAR0+12 ;ditto for V.Loc 120000 to 137777
RTS PC
UNHOLD: MOV #UHLDMS,R1
BR OUTSTR
HOLD: MOV #HLDMS,R1
OUTSTR: MOVB (R1)+,R0 ;Get next char
BEQ 1$ ;If done - quit
JSR PC,OUTCHR ;Print it
BR OUTSTR
1$: JSR PC,OUTCHR ;Print a couple nulls
JSR PC,OUTCHR
JMP OUTCHR
OUTNUM: CLR R0
ASHC #1,R0 ;Get high bit
ADD #'0,R0 ;Convert it to ASCII
JSR PC,OUTCHR ; & print it
OUTNM1: MOV R2,-(SP)
MOV #5,R2 ;Get low 5 digits
OUTNM2: CLR R0
ASHC #3,R0 ;Get next digit
ADD #'0,R0 ;Convert it to ASCII
JSR PC,OUTCHR ; & print it
SOB R2,OUTNM2 ;Do it all
MOV (SP)+,R2
RTS PC
OUTNMN: MOV R2,-(SP) ;Entry point for only a few digits, # in R1
MOV R0,R2
BR OUTNM2
OUTCHR: TST OUTSW ;Who does it go to?
BEQ 2$
1$: TSTB KBOS ;VT05 ready?
BPL 1$ ;Loop til it is
MOVB R0,KBOR ;Print the char
RTS PC
2$: TSTB OREG ;Console ready?
BNE 2$ ;Wait til it is
MOVB R0,OREG ;Output char
RTS PC
;Constants & Data
PARNUM: 0 ;Number of parity errors
ERRNUM: 0 ;Number of errors
ITER: 0
CHUNK: 7
TEST: 5
WRTRD: 0 ;Writing (0) or reading (1)
VSW: SW ;So I can run this from home without having to worry
PGTBL0: .WORD 0,200,400,600,1000,1200,1400,7600
TESTS: TEST1 ;Write all zeros
TEST2 ; all ones
TEST3 ; 0101...
TEST4 ; 1010...
TEST5 ; addresses (ascending)
TEST6 ; complement of addresses (descending)
TEST1 ;Until something better comes along for test #7
TSTERR: PATERR ;Write all zeros
PATERR ; all ones
PATERR ; 0101...
PATERR ; 1010...
T5ERR ; addresses (ascending)
T6ERR ; complement of addresses (descending)
PATERR ;Until something better comes along for test #7
;Now all those ASCII strings for the various messages
BEGMES: .ASCII /πMemory diagnostic program (did you set core to 16K?)/
CRLF: .BYTE 12,15,0
NXMMES: .ASCIZ /πNXM at: /
MAPMES: .ASCIZ /πMapper error at: /
ERR1: .ASCIZ /πError address: /
ERR2: .ASCIZ / Correct: /
ERR3: .ASCIZ / Error: /
err5: .asciz / test# /
ERR1P: .ASCIZ /πParity error - we lose big since this memory doesn't generate them!!
/
.EVEN
SETOM: MOV #LOW,R1 ;random routine to call from ddt
SETOM1: MOV #-1,(R1)+
CMP R1,#HI
BLO SETOM1
BPT
patch: .blkw 100
.END START